package com.talkyun.utils;

import com.talkyun.utils.cache.LruHashMap;
import com.talkyun.utils.crypt.KeyStringCrypt;
import com.talkyun.utils.crypt.KeyStringUtils;
import com.talkyun.utils.http.HttpConnector;
import com.talkyun.utils.http.HttpResult;

import java.io.IOException;

import static java.lang.Thread.sleep;
import static java.util.concurrent.TimeUnit.MINUTES;

public class KeyStringManager {
    private static LruHashMap<String, String> CACHE = new LruHashMap<>(1024);

    private String url;
    private String publicKey;
    private KeyStringCrypt rsaCrypt;

    public KeyStringManager() {
        this("https://openx.talkyun.com/data/key/");
    }

    public KeyStringManager(String url) {
        this.url = url;
    }

    public void setPublicKey(String publicKey) {
        this.publicKey = publicKey;
    }

    public String getKeyString(String id) {
        if (id == null || id.trim().length() == 0) {
            throw new RuntimeException("Id error! " + id);
        }
        id = KeyStringUtils.cleanKeyString(id);

        long now = System.currentTimeMillis();
        String item = CACHE.get(id);
        if (item != null) {
            String ts = item.substring(0, 13);
            long time = Long.parseLong(ts);
            if ((now - time) < MINUTES.toMillis(3)) {
                return item.substring(13);
            }
        }

        String prefix = id.substring(0, 8);
        String fullUrl = url + prefix + "/" + id.substring(8);

        for (int i = 0; i < 3; i++) {
            try {
                long beg = System.currentTimeMillis();
                String body = this.doGetKeyString(fullUrl);
                System.out.println("Http:" + (System.currentTimeMillis() - beg));
                if (body == null) {
                    return null;
                }
                String keyString = getRsaCrypt().decrypt(body);
                CACHE.put(id, now + keyString);
                return keyString;
            } catch (IOException ignored) {
                try {
                    sleep(700 * (i + 1));
                } catch (InterruptedException e) {
                    // ignore
                }
            }
        }

        // last safe
        if (item != null) {
            return item;
        }

        throw new RuntimeException("Can't get key string! " + id);
    }

    private String doGetKeyString(String url) throws IOException {
        HttpConnector http = new HttpConnector(url + "?" + System.currentTimeMillis());
        HttpResult result = http.sendWithHeader("GET", null, null);
        if (result.getStatus() >= 200 && result.getStatus() < 300) {
            return result.getResult();
        } else if (result.getStatus() == 404) {
            return null;
        } else {
            throw new IOException(result.getStatus() + ":" + result.getResult());
        }
    }

    private KeyStringCrypt getRsaCrypt() {
        if (rsaCrypt != null) {
            return rsaCrypt;
        }

        if (publicKey != null) {
            rsaCrypt = new KeyStringCrypt(publicKey, null);
        } else {
            rsaCrypt = new KeyStringCrypt();
        }

        return rsaCrypt;
    }

    public static void main(String[] args) {
        KeyStringCrypt ksc = new KeyStringCrypt();
        // System.out.println(ksc.encrypt("hello world! "));

        long time = System.currentTimeMillis();
        KeyStringManager ksm = new KeyStringManager();
        ksm.setPublicKey(KeyStringCrypt.DEFAULT_PUBLIC_KEY);

        System.out.println(ksm.getKeyString("20210811/BmuuSr1FjQoFcnQV1nHd1nIVAp34sl3Z"));
        System.out.println(System.currentTimeMillis() - time);

        System.out.println(ksm.getKeyString("20210811/BmuuSr1FjQoFcnQV1nHd1nIVAp34sl3Z"));
        System.out.println(System.currentTimeMillis() - time);
        System.out.println(ksm.getKeyString("20210811/BmuuSr1FjQoFcnQV1nHd1nIVAp34sl4X"));
        System.out.println(System.currentTimeMillis() - time);
    }
}
